#include "tcpsocket.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QEventLoop>
#include <QTimer>

TcpSocket::TcpSocket(QTcpSocket* sock, QObject* parent)
    : QObject(parent)
{
    if (sock != nullptr)
        socket = sock;
    else
        socket = new QTcpSocket();
    connect(socket, &QTcpSocket::readyRead,
        this, &TcpSocket::OnReadyRead);
    connect(socket, &QTcpSocket::disconnected,
        this, &TcpSocket::Disconnected);
}

TcpSocket::~TcpSocket()
{
    if (socket) {
        socket->deleteLater();
    }
}

bool TcpSocket::IfConnected()
{
    return socket->state() == QAbstractSocket::ConnectedState;
}

bool TcpSocket::ConnectToServer(const QString& host, unsigned int port)
{
    if (socket->state() == QAbstractSocket::ConnectedState) {
        if (socket->peerAddress() == QHostAddress(host)
            && socket->peerPort() == port) {
            return true;
        } else {
            socket->disconnectFromHost();
        }
    }
    QEventLoop loop;
    connect(socket, &QTcpSocket::connected,
        &loop, &QEventLoop::quit);
    QTimer timer;
    timer.setSingleShot(true);
    timer.setInterval(5000);
    connect(&timer, &QTimer::timeout,
        &loop, &QEventLoop::quit);
    timer.start();
    socket->connectToHost(host, port);
    loop.exec();
    return timer.isActive();
}

void TcpSocket::Disconnect()
{
    if (socket->state() == QAbstractSocket::ClosingState || socket->state() == QAbstractSocket::UnconnectedState) {
        return;
    }

    //socket->disconnectFromHost();
    //return;

    QEventLoop loop;
    connect(socket, &QTcpSocket::disconnected,
        &loop, &QEventLoop::quit);
    QTimer timer;
    timer.setSingleShot(true);
    timer.setInterval(5000);
    connect(&timer, &QTimer::timeout,
        &loop, &QEventLoop::quit);
    timer.start();
    socket->disconnectFromHost();
    if (socket->state() != QAbstractSocket::UnconnectedState)
        loop.exec();
}

bool TcpSocket::WriteData(const QByteArray& data)
{
    qint64 l = socket->write(data);
    socket->flush();
    return l == data.length();
}

bool TcpSocket::WaitForWritten(int ms)
{
    return true;
    if (ms <= 0)
        ms = 3000;
    return socket->waitForBytesWritten(ms);
    QEventLoop loop;
    connect(socket, &QTcpSocket::bytesWritten,
        &loop, &QEventLoop::quit);
    QTimer timer;
    timer.setSingleShot(true);
    timer.setInterval(ms);
    connect(&timer, &QTimer::timeout,
        &loop, &QEventLoop::quit);
    timer.start();
    loop.exec();
    return timer.isActive();
}

void TcpSocket::OnReadyRead()
{
    emit DataReady(socket->readAll());
}
